package com.corticon.dialogs.model;

import java.io.Serializable;
import java.util.*;

import javax.persistence.*;

import org.hibernate.validator.Length;
import org.hibernate.validator.NotEmpty;
import org.hibernate.validator.NotNull;

/**
 * @author Lifan Yang
 */
@NamedQueries( { @NamedQuery(name = "Questionnaire.findMaxRefId", query = "select max(qn.refId) from Questionnaire qn"),
		@NamedQuery(name = "Questionnaire.findMaxVersionByRefId", query = "select max(qn.version) from Questionnaire qn where qn.refId = :refId") })
@Entity
@Table(name = "q_dialog", uniqueConstraints = { @UniqueConstraint(columnNames = { "ID", "VERSION" }) })
public class Questionnaire extends QuestionBase implements Serializable {

	private Long questionnaireId;

	// ********** Questionnaire Properties ********** //
	private Questionnaire sibling;
	private Set<QuestionSetInNaire> questionSetsInNaire = new HashSet<QuestionSetInNaire>();

	// ********** QL Properties ********** //
	private ProductType productType;
	private Region region;
	private Function function;
	private Theme theme;
	private Locale locale;
	private DataValidation defaultTimeMask;
	private DataValidation defaultDateMask;
	private DataValidation defaultDateTimeMask;

	// Publish Properties
	private User publishedBy;
	private Date publishedOn;
	private String publishText;

	// Other Properties
	private String decisionServiceName;
	private String decisionServiceVersion;
	private String displayFlag;
	private String displayTitle;
	private Date effectiveDate;
	private Date expirationDate;
	private Boolean summaryReport;
	private PublicationStatusType publicationStatus;
	private boolean enableSave;
	private String exitpageurl;

	public Questionnaire() {
	}

	public static Questionnaire newInstance() {
		Questionnaire instance = new Questionnaire();

		instance.productType = new ProductType();
		instance.region = new Region();
		instance.function = new Function();
		instance.theme = new Theme();
		instance.locale = new Locale();
		instance.defaultDateMask = new DataValidation();
		instance.defaultDateTimeMask = new DataValidation();
		instance.defaultTimeMask = new DataValidation();

		return instance;
	}

	@Id
	@SequenceGenerator(name = "q_dialog_id_seq", sequenceName = "q_dialog_id_seq", allocationSize = 1, initialValue = 1)
	// Set allocationSize and initialValue
	// to let sequence increment following DB.
	@GeneratedValue(strategy = GenerationType.AUTO, generator = "q_dialog_id_seq")
	@Column(name = "q_dialog_id", columnDefinition = "integer")
	public Long getQuestionnaireId() {
		return this.questionnaireId;
	}

	public void setQuestionnaireId(Long questionnaireId) {
		this.questionnaireId = questionnaireId;
	}

	// ********** Questionnaire Accessors ********** //
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "sib_dialassoc_q_dialog_id_oid")
	public Questionnaire getSibling() {
		return this.sibling;
	}

	public void setSibling(Questionnaire sibling) {
		this.sibling = sibling;
	}

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "questionnaire")
	@OrderBy("sequence asc")
	public Set<QuestionSetInNaire> getQuestionSetsInNaire() {
		return this.questionSetsInNaire;
	}

	public void setQuestionSetsInNaire(Set<QuestionSetInNaire> questionSetsInNaire) {
		this.questionSetsInNaire = questionSetsInNaire;
	}

	// ********** QL Accessors ********** //

	// @NotNull(message = "questionnaire.validate.productType.required")

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "productassoc_code_oid", nullable = false)
	public ProductType getProductType() {
		return this.productType;
	}

	public void setProductType(ProductType productType) {
		this.productType = productType;
	}

	// @NotNull(message = "questionnaire.validate.region.required")
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "regionassoc_code_oid", nullable = false)
	public Region getRegion() {
		return this.region;
	}

	public void setRegion(Region region) {
		this.region = region;
	}

	// @NotNull(message = "questionnaire.validate.function.required")
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "functionassoc_code_oid", nullable = false)
	public Function getFunction() {
		return this.function;
	}

	public void setFunction(Function function) {
		this.function = function;
	}

	// @NotNull(message = "questionnaire.validate.theme.required")
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "themeassoc_code_oid", nullable = false)
	public Theme getTheme() {
		return this.theme;
	}

	public void setTheme(Theme theme) {
		this.theme = theme;
	}

	// @NotNull(message = "questionnaire.validate.locale.required")
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "localecode")
	public Locale getLocale() {
		return this.locale;
	}

	public void setLocale(Locale locale) {
		this.locale = locale;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "deftimemaskassoc_code_oid")
	public DataValidation getDefaultTimeMask() {
		return this.defaultTimeMask;
	}

	public void setDefaultTimeMask(DataValidation defaultTimeMask) {
		this.defaultTimeMask = defaultTimeMask;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "defdatemaskassoc_code_oid")
	public DataValidation getDefaultDateMask() {
		return this.defaultDateMask;
	}

	public void setDefaultDateMask(DataValidation defaultDateMask) {
		this.defaultDateMask = defaultDateMask;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "defdatetimemaskassoc_code_oid")
	public DataValidation getDefaultDateTimeMask() {
		return this.defaultDateTimeMask;
	}

	public void setDefaultDateTimeMask(DataValidation defaultDateTimeMask) {
		this.defaultDateTimeMask = defaultDateTimeMask;
	}

	// ******** Publish Accessors ********** //
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "publishedbyassoc_userid_oid")
	public User getPublishedBy() {
		return this.publishedBy;
	}

	public void setPublishedBy(User publishedBy) {
		this.publishedBy = publishedBy;
	}

	@Temporal(TemporalType.DATE)
	@Column(name = "published", length = 19)
	public Date getPublishedOn() {
		return this.publishedOn;
	}

	public void setPublishedOn(Date publishedOn) {
		this.publishedOn = publishedOn;
	}

	@Length(max = 255, message = "dialog.publishtext.length")
	@Column(name = "publishtext", length = 255)
	public String getPublishText() {
		return this.publishText;
	}

	public void setPublishText(String publishText) {
		this.publishText = publishText;
	}

	// ********** Other Accessors ********** //
	@Column(name = "decisionservicename", length = 255)
	public String getDecisionServiceName() {
		return this.decisionServiceName;
	}

	public void setDecisionServiceName(String decisionServiceName) {
		this.decisionServiceName = decisionServiceName;
	}

	@Length(max = 255, message = "dialog.descisionserviceversion.length")
	@Column(name = "decisionserviceversion", length = 255)
	public String getDecisionServiceVersion() {
		return this.decisionServiceVersion;
	}

	public void setDecisionServiceVersion(String decisionServiceVersion) {
		this.decisionServiceVersion = decisionServiceVersion;
	}

	@Column(name = "displayflag", length = 255)
	public String getDisplayFlag() {
		return this.displayFlag;
	}

	public void setDisplayFlag(String displayFlag) {
		this.displayFlag = displayFlag;
	}

	@Length(max = 255, message = "dialog.displaytitle.length")
	@Column(name = "displaytitle", length = 255)
	public String getDisplayTitle() {
		return this.displayTitle;
	}

	public void setDisplayTitle(String displayTitle) {
		this.displayTitle = displayTitle;
	}

	@Temporal(TemporalType.DATE)
	@Column(name = "effectivedate", length = 19)
	public Date getEffectiveDate() {
		return this.effectiveDate;
	}

	public void setEffectiveDate(Date effectiveDate) {
		this.effectiveDate = effectiveDate;
	}

	@Temporal(TemporalType.DATE)
	@Column(name = "expirationdate", length = 19)
	public Date getExpirationDate() {
		return this.expirationDate;
	}

	public void setExpirationDate(Date expirationDate) {
		this.expirationDate = expirationDate;
	}

    @NotNull(message = "dialog.summaryReport.NotNull")
	@Column(name = "summaryReport")
	public Boolean getSummaryReport() {
		return this.summaryReport;
	}

	public void setSummaryReport(Boolean summaryReport) {
		// this.summaryReport = summaryReport == null ? false : summaryReport;
		this.summaryReport = summaryReport;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "publstatusassoc_code_oid")
	public PublicationStatusType getPublicationStatus() {
		return this.publicationStatus;
	}

	public void setPublicationStatus(PublicationStatusType publicationStatus) {
		this.publicationStatus = publicationStatus;
	}

	@Column(name = "enable_save")
	public boolean getEnableSave() {
		return enableSave;
	}

	public void setEnableSave(boolean enableSave) {
		this.enableSave = enableSave;
	}

	@Column(name = "exitpageurl", length = 1999)
	public String getExitpageurl() {
		return exitpageurl;
	}

	public void setExitpageurl(String exitpageurl) {
		this.exitpageurl = exitpageurl;
	}

    @Transient
    public List<QuestionSetInNaire> getSortedPages(){
        List<QuestionSetInNaire> sortedPages = new ArrayList<QuestionSetInNaire>(this.questionSetsInNaire);
        Collections.sort(sortedPages);
        return sortedPages;
    }
}